
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Spring Bean 如何保证并发安全？ - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>Spring Bean 如何保证并发安全？ - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">为什么在 Spring 框架中，单例（Singleton）作用域的 Bean 需要特别关注并发安全问题？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">因为单例 Bean 在整个 Spring 容器中只有一个实例，多个线程可能会同时访问这一个实例，如果没有适当的并发控制，就可能导致数据不一致或其他线程安全问题。</div>
          </div>
          <div class="card-source">来源: 文档引言部分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">根据文档，实现 Bean 线程安全最简单、最自然的方式是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">避免使用可变状态。如果一个 Bean 的状态是不可变的，例如将其属性设置为 `final`，那么它天生就是线程安全的。</div>
          </div>
          <div class="card-source">来源: 1. 避免使用可变状态</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">当 Bean 必须包含共享状态时，除了使用 `synchronized` 关键字，还可以使用哪些类型的工具来保证线程安全？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">可以使用线程安全的数据结构，例如 `ConcurrentHashMap` 或 `AtomicInteger`。这些数据结构内置了线程安全的机制来处理并发访问。</div>
          </div>
          <div class="card-source">来源: 2. 使用线程安全的数据结构</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">`synchronized` 关键字是如何保证对共享资源访问的线程安全的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">同步机制（`synchronized`）确保一次只有一个线程能够访问被其修饰的共享资源代码块或方法，从而避免了多线程冲突。</div>
          </div>
          <div class="card-source">来源: 3. 同步访问共享资源</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">为什么在 Bean 的方法中使用局部变量是线程安全的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">因为局部变量是在方法内部定义的，每次方法调用时都会为当前线程创建新的局部变量副本，线程之间不会共享局部变量，所以它们天生就是线程安全的。</div>
          </div>
          <div class="card-source">来源: 4. 使用局部变量</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">当不希望在多个线程间共享某个变量，而是为每个线程维护一个独立的副本时，应该使用什么技术？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">可以使用线程局部存储（Thread-Local）。`ThreadLocal` 可以为每个线程提供一个独立的变量副本，适合用于保存线程私有的数据。</div>
          </div>
          <div class="card-source">来源: 6. 使用线程局部存储（Thread-Local）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">除了在 Bean 内部实现线程安全逻辑，还有什么Spring特有的方法可以从设计上规避并发问题？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">可以考虑改变 Bean 的作用域。例如，使用 `@RequestScope` 作用域，Spring 会为每个 HTTP 请求创建一个新的 Bean 实例，这样就自然避免了不同请求之间的状态共享和并发问题。</div>
          </div>
          <div class="card-source">来源: 7. 考虑 Bean 的作用域</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">在 Spring Bean 的生命周期管理中，`@PostConstruct` 和 `@PreDestroy` 注解在确保线程安全方面有什么作用？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">这两个注解可以用来定义 Bean 的初始化和销毁逻辑。开发者可以利用它们来确保 Bean 在初始化和销毁这两个关键阶段的操作是线程安全的。</div>
          </div>
          <div class="card-source">来源: 5. 使用线程安全的 Bean 生命周期管理</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">文档中提到的 `AtomicInteger` 和 `synchronized` 方法都能实现一个线程安全的计数器，它们在机制上有什么不同？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`synchronized` 是一种同步锁机制，它通过锁定整个方法来保证同一时间只有一个线程可以执行它。而 `AtomicInteger` 是一个内置了线程安全机制的数据结构，它通过更底层的原子操作来处理并发访问，而无需锁定整个方法。</div>
          </div>
          <div class="card-source">来源: 2. 使用线程安全的数据结构 和 3. 同步访问共享资源</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
